package com.woniu.user.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.user.controller.form.SearchForm;
import com.woniu.user.exception.WebException;
import com.woniu.user.exception.WebExceptionCode;
import com.woniu.user.model.*;
import com.woniu.user.dao.OrderDao;
import com.woniu.user.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.user.service.dto.OrderDto;
import com.woniu.user.util.BeanCopyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * <p>
 * 订单信息表 服务实现类
 * </p>
 *
 * @author Silas
 * @since 2023-02-15
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderDao, Order> implements OrderService {
    @Resource
    private OrderDao orderDao;
    @Resource
    private LessonService lessonService;
    @Resource
    private CoachService coachService;
    @Resource
    private RocketMQTemplate mqTemplate;
    @Resource
    private AccountService accountService;
    @Resource
    private OccupyService occupyService;

    @Override
    public Page<Order> query(Integer userId, Integer current, Integer size, String condition) {
        Integer coachId = coachService.getOne(new QueryWrapper<Coach>().eq("account_id", userId)).getCoachId();
        System.out.println(coachId);
        Page<Order> page = new Page<>(current == null ? 1 : current, size == null ? 4 : size);
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("coach_id", coachId).orderByDesc("order_id");
        if (!("".equals(condition) || condition == null)) {
            queryWrapper.eq("state", condition)
                    .or().eq("user_name", condition)
                    .or().like("no", condition)
                    .or().like("lesson_name", condition);
        }
        Page<Order> orderPage = orderDao.selectPage(page, queryWrapper);
        System.out.println(orderPage);
        return orderPage;
    }

    @Override
    public void createOrder(Book book) {
        Lesson lesson = lessonService.getById(book.getLessonId());
        Order order = BeanCopyUtil.copyObject(book, Order.class);
        Snowflake snowflake = new Snowflake(1, 1);
        String no = snowflake.nextIdStr();
        order.setNo(no);
        order.setCreateTime(LocalDateTime.now());
        order.setPrice(lesson.getPrice());
        order.setState("待支付");
        save(order);
        // 生成消息体发送到mq
        OrderDto orderDto = BeanCopyUtil.copyObject(order, OrderDto.class);
        orderDto.setOperationType("创建订单");
        orderDto.setLogInfo(book.getUserName()+"创建订单");
        SendResult sendResult = mqTemplate.syncSend("order-topic", orderDto);
        log.info("创建订单日志 {}", sendResult);
    }

    // 查看我的订单
    @Override
    public IPage<Order> getMyOrder(Integer userId, Page<Order> orderPage) {
        return this.baseMapper.selectPage(orderPage, new QueryWrapper<Order>().eq("user_id", userId).orderByDesc("order_id"));
    }

    // 学员初次付款
    @Override
    @Transactional
    public void pay(Integer orderId, Integer userId, String password) {
        // 获取学员账户
        Account account = accountService.getById(userId);
        if (account == null) throw new WebException(WebExceptionCode.USER_IS_NOT_EXISTS);
        if (!account.getPassword().equals(password)) throw new WebException(WebExceptionCode.PASSWORD_IS_NOT_RIGHT);
        // 获取订单
        Order order = this.getById(orderId);
        if(order == null) throw new WebException(WebExceptionCode.ORDER_IS_NOT_EXISTS);
        // 判断学员id和订单中的用户id是否一致
        Integer orderUserId = order.getUserId();
        if (!Objects.equals(userId, orderUserId)) throw new WebException(WebExceptionCode.ORDER_INFO_INCORRECT);
        // 判断学员账户余额是否充足
        BigDecimal amount = order.getPrice();
        BigDecimal balance = account.getBalance();
        if(amount.compareTo(balance) == 1) throw new WebException(WebExceptionCode.BALANCE_IS_NOT_ENOUGH);
        // 学员新的账户余额
        BigDecimal userMoney = balance.subtract(amount);
        account.setBalance(userMoney);
        accountService.updateById(account);
        // 改订单
        order.setPayTime(LocalDateTime.now());// 付款时间
        order.setState("已支付待完成");
        order.setTempMoney(amount);// 平台暂存的钱
        this.updateById(order);
        // 发订单日志
        OrderDto orderDto = BeanCopyUtil.copyObject(order, OrderDto.class);
        orderDto.setOperationType("支付订单到平台");
        orderDto.setLogInfo(order.getUserName()+"支付订单到平台");
        SendResult sendResult = mqTemplate.syncSend("order-topic", orderDto);
        log.info("首次支付订单日志 {}", sendResult);
    }

    // 学员取消订单
    @Override
    public void cancel(Integer orderId, Integer userId) {
        // 获取学员账户
        Account account = accountService.getById(userId);
        if (account == null) throw new WebException(WebExceptionCode.USER_IS_NOT_EXISTS);
        // 获取订单
        Order order = this.getById(orderId);
        if(order == null) throw new WebException(WebExceptionCode.ORDER_IS_NOT_EXISTS);
        // 修改订单状态
        order.setState("已取消");
        this.updateById(order);
        // 移除时间占用
        LocalDateTime lessonTime = order.getLessonTime();
        Integer coachId = order.getCoachId();
        boolean flag = occupyService.remove(new UpdateWrapper<Occupy>().eq("time", lessonTime).eq("user_id", userId).eq("coach_id", coachId));
        if(!flag) throw new WebException(WebExceptionCode.OCCUPY_ERROR);
        // 订单日志
        OrderDto orderDto = BeanCopyUtil.copyObject(order, OrderDto.class);
        orderDto.setOperationType("未支付取消订单");
        orderDto.setLogInfo(order.getUserName()+"未支付取消订单");
        SendResult sendResult = mqTemplate.syncSend("order-topic", orderDto);
        log.info("未支付取消订单 {}", sendResult);

    }

    // 上完课确认付款
    @Override
    public void checkPay(Integer orderId, Integer userId, String password) {
        // 获取学员账户
        Account account = accountService.getById(userId);
        if (account == null) throw new WebException(WebExceptionCode.USER_IS_NOT_EXISTS);
        if (!account.getPassword().equals(password)) throw new WebException(WebExceptionCode.PASSWORD_IS_NOT_RIGHT);
        // 获取订单
        Order order = this.getById(orderId);
        if(order == null) throw new WebException(WebExceptionCode.ORDER_IS_NOT_EXISTS);
        // 判断学员id和订单中的用户id是否一致
        Integer orderUserId = order.getUserId();
        if (!Objects.equals(userId, orderUserId)) throw new WebException(WebExceptionCode.ORDER_INFO_INCORRECT);
        // 获取教练信息
        Integer coachId = order.getCoachId();
        Coach coach = coachService.getById(coachId);
        if(coach == null) throw new WebException(WebExceptionCode.COACH_IS_NOT_EXISTS);
        // 获取订单暂存金额并更新教练账户信息
        BigDecimal tempMoney = order.getTempMoney();
        Integer coachAccountId = coach.getAccountId();
        Account coachAccount = accountService.getById(coachAccountId);
        if(coachAccount == null) throw new WebException(WebExceptionCode.USER_IS_NOT_EXISTS);
        BigDecimal coachBalance = coachAccount.getBalance();
        BigDecimal newBalance = coachBalance.add(tempMoney);
        coachAccount.setBalance(newBalance);
        accountService.updateById(coachAccount);
        // 改订单
        order.setPayTime(LocalDateTime.now());// 付款时间
        order.setState("已完成");
        order.setTempMoney(BigDecimal.ZERO);// 平台暂存的钱
        this.updateById(order);
        // 发订单日志
        OrderDto orderDto = BeanCopyUtil.copyObject(order, OrderDto.class);
        orderDto.setOperationType("上完课支付订单");
        orderDto.setLogInfo(order.getUserName()+"上完课支付订单");
        SendResult sendResult = mqTemplate.syncSend("order-topic", orderDto);
        log.info("上完课支付订单 {}", sendResult);
    }

    // 学员申请退款
    @Override
    public void applyBack(Integer orderId, String reason, Integer userId) {
        // 获取学员账户
        Account account = accountService.getById(userId);
        if (account == null) throw new WebException(WebExceptionCode.USER_IS_NOT_EXISTS);
        // 获取订单
        Order order = this.getById(orderId);
        if(order == null) throw new WebException(WebExceptionCode.ORDER_IS_NOT_EXISTS);
        // 修改订单信息
        order.setState("退款中");
        order.setNote(reason);
        this.updateById(order);
        // 订单日志
        OrderDto orderDto = BeanCopyUtil.copyObject(order, OrderDto.class);
        orderDto.setOperationType("学员申请退款");
        orderDto.setLogInfo(order.getUserName()+"申请退款");
        SendResult sendResult = mqTemplate.syncSend("order-topic", orderDto);
        log.info("申请退款日志 {}", sendResult);
    }

    // 搜索订单
    @Override
    public IPage<Order> search(SearchForm form, Integer userId) {
        Account account = accountService.getById(userId);
        if (account == null) throw new WebException(WebExceptionCode.USER_IS_NOT_EXISTS);
        Integer page = form.getPage();
        Integer size = form.getSize();
        String key = form.getKey();
        Page<Order> orderPage = new Page<>(page, size);
        QueryWrapper<Order> wrapper = new QueryWrapper<Order>().eq("user_id", userId);
        wrapper.like("no", key).or().like("coach_name", key).or().like("lesson_name", key).or().like("state", key);
        return this.baseMapper.selectPage(orderPage, wrapper);
    }
}
